package com.syh.jn.scm.domain.operation.entity.supplier;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.util.other.ExtStringUtils;
import cn.redscarf.commons.spring.SpringContextUtils;
import cn.redscarf.commons.util.validator.ValidationUtils;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.domain.AbstractSimpleAggregate;
import com.syh.core.ddd.domain.CodeExpEnum;
import com.syh.core.ddd.domain.CodeGenerateUtil;
import com.syh.jn.scm.domain.supplier.repository.finance.CostBillReadRepository;
import com.syh.jn.scm.domain.supplier.repository.finance.IncomeBillReadRepository;
import com.syh.jn.scm.domain.supplier.repository.purchase.PurReturnOrderReadRepository;
import com.syh.jn.scm.domain.supplier.repository.purchase.PurchaseOrderReadRepository;
import com.syh.jn.scm.domain.supplier.repository.sale.SaleOrderReadRepository;
import com.syh.jn.scm.domain.supplier.repository.sale.SaleReturnOrderReadRepository;
import com.syh.jn.scm.domain.supplier.repository.stock.StockLossReadRepository;
import com.syh.jn.scm.domain.supplier.repository.stock.StockOtherInBillReadRepository;
import com.syh.jn.scm.domain.supplier.repository.stock.StockOtherOutBillReadRepository;
import com.syh.jn.scm.domain.supplier.repository.stock.StockSpillReadRepository;
import com.syh.jn.scm.dto.operation.supplier.OperaSupplierMto;
import com.syh.jn.scm.dto.operation.supplier.OperaSupplierSto;
import com.syh.jn.scm.exception.BusinessException;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 运营端供应商聚合
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class OperaSupplier extends AbstractSimpleAggregate<Long> {
  /**
   * 单位名称
   */
  private String name;
  /**
   * 法人代表
   */
  private String legalRepresentative;
  /**
   * 注册资金（单位 ：万元）
   */
  private Integer registeredCapital;
  /**
   * 工商注册号
   */
  private String registrationCode;
  /**
   * 地址省 市 区
   */
  private String area;
  /**
   * 地区编号
   */
  private String areaCode;
  /**
   * 单位注册地址
   */
  private String address;
  /**
   * 是否是合资、子公司: -1不是, 1是
   */
  private Short isSubsidiary;
  /**
   * 单位编号
   */
  private String code;
  /**
   * 状态: -1停用, 1可用
   */
  private Short status;
  /**
   * 对公电子邮件
   */
  private String email;
  /**
   * 公司联系电话
   */
  private String tel;
  /**
   * 营业执照图片url,保存格式json字符串{"img":"www.test.com","img":"www.demo.com"}
   */
  private String businessLicense;
  /**
   * 合同图片url,保存格式json字符串{"img":"www.test.com","img":"www.demo.com"}
   */
  private String contract;
  /**
   * 开账状态: 0未开账, 1已开账
   */
  private Short openAccountState;
  /**
   * 开账时间
   */
  private Long openAccountTimeStamp;
  /**
   * 地址明细
   */
  private List<OperaSupplierAddress> addressItem;


  public OperaSupplier() {
  }

  public OperaSupplier(OperaSupplierSto sto) {
    ExtAssert.notNull(sto, "对象为空");
    ValidationUtils.validate(sto);
    ExtBeanUtils.copyProperties(sto, this);
    //启用
    this.enabled();
    //供应商
    this.uuid = UUID.randomUUID().toString();
    this.createTimeStamp = System.currentTimeMillis();
    this.code = CodeGenerateUtil.merchantCodeGenerate(CodeExpEnum.SUPPLIER_CODE_EXP.getCodeExp());
    this.openAccountState = 0;
    //添加明细
    this.addressItem = new ArrayList<>();
    sto.getAddressItem().stream().forEach(addressSto -> {
      this.addItem(new OperaSupplierAddress(addressSto));
    });
  }

  /**
   * 添加地址项
   *
   * @param item
   * @return
   */
  public OperaSupplier addItem(OperaSupplierAddress item) {
    this.addressItem.add(item);
    return this;
  }

  /**
   * 运营修改供应商
   *
   * @param mto
   */
  public void modify(OperaSupplierMto mto) {
    ExtAssert.notNull(mto, "对象为空");
    ValidationUtils.validate(mto);
    ExtBeanUtils.copyProperties(mto, this);
    //code不符合规则则重新生成code
    if (!CodeGenerateUtil.checkExp(CodeExpEnum.SUPPLIER_CODE_EXP.getCodeRegexp(), this.code)) {
      this.code = CodeGenerateUtil.merchantCodeGenerate(CodeExpEnum.SUPPLIER_CODE_EXP.getCodeExp());
    }

    this.addressItem = new ArrayList<>();
    mto.getAddressItem().stream().forEach(addressMto -> {
      OperaSupplierAddress operaSupplierAddress = new OperaSupplierAddress(addressMto);
      this.addItem(operaSupplierAddress);
    });

    // 这里只是一个数据的修正方案，正常逻辑uuid不会为空
    if (ExtStringUtils.isEmpty(this.uuid)) {
      this.uuid = UUID.randomUUID().toString();
    }
    this.lastUpdateTimeStamp = System.currentTimeMillis();
  }


  /**
   * 启用
   */
  public void enabled() {
    this.status = 1;
  }

  /**
   * 停用
   */
  public void disabled() {
    this.status = -1;
  }

  /**
   * 开账
   */
  public void openAccount() {
    if (Short.valueOf("1").equals(this.openAccountState)) {
      throw new BusinessException(this.name+"已开账！开账失败！");
    }
    this.openAccountTimeStamp = System.currentTimeMillis();
    this.openAccountState = 1;
  }

  /**
   * 反开账
   */
  public void reversalAccount() {
    if (Short.valueOf("0").equals(this.openAccountState)) {
      throw new BusinessException(this.name+"未开账！反开账失败！");
    }
    SaleOrderReadRepository saleOrderReadRepository = (SaleOrderReadRepository) SpringContextUtils.getBean("saleOrderRepositoryImpl");
    Wrapper saleWp = Wrapper.build().append(Restrictions.eq("businessEntityId",this.id)).append(Restrictions.ne("ordState",Short.valueOf("-1")));
    if (saleOrderReadRepository.getCount(saleWp) > 0) {
      throw new BusinessException(this.name+"存在未取消的销售订单！反开账失败！");
    }
    SaleReturnOrderReadRepository saleReturnOrderReadRepository = (SaleReturnOrderReadRepository) SpringContextUtils.getBean("saleReturnOrderRepositoryImpl");
    Wrapper saleReturnWp = Wrapper.build().append(Restrictions.eq("businessEntityId",this.id)).append(Restrictions.ne("returnOrdState",Short.valueOf("-1")));
    if (saleReturnOrderReadRepository.getCount(saleReturnWp) > 0) {
      throw new BusinessException(this.name+"存在未取消的销售退货订单！反开账失败！");
    }
    PurchaseOrderReadRepository purchaseOrderReadRepository = (PurchaseOrderReadRepository) SpringContextUtils.getBean("purchaseOrderRepositoryImpl");
    Wrapper purWp = Wrapper.build().append(Restrictions.eq("businessEntityId",this.id)).append(Restrictions.ne("ordState",Short.valueOf("-1")));
    if (purchaseOrderReadRepository.getCount(purWp) > 0) {
      throw new BusinessException(this.name+"存在未取消的采购订单！反开账失败！");
    }
    PurReturnOrderReadRepository purReturnOrderReadRepository = (PurReturnOrderReadRepository) SpringContextUtils.getBean("purchaseReturnOrderRepositoryImpl");
    Wrapper purReturnWp = Wrapper.build().append(Restrictions.eq("businessEntityId",this.id)).append(Restrictions.ne("returnOrdState",Short.valueOf("-1")));
    if (purReturnOrderReadRepository.getCount(purReturnWp) > 0) {
      throw new BusinessException(this.name+"存在未取消的采购退货订单！反开账失败！");
    }
    CostBillReadRepository costBillReadRepository = (CostBillReadRepository) SpringContextUtils.getBean("costBillRepositoryImpl");
    Wrapper costWp = Wrapper.build().append(Restrictions.eq("businessEntityId",this.id)).append(Restrictions.ne("state",Short.valueOf("-1")));
    if (costBillReadRepository.getCount(costWp) > 0) {
      throw new BusinessException(this.name+"存未取消的费用单！反开账失败！");
    }
    IncomeBillReadRepository incomeBillReadRepository = (IncomeBillReadRepository) SpringContextUtils.getBean("incomeBillRepositoryImpl");
    Wrapper incomeWp = Wrapper.build().append(Restrictions.eq("businessEntityId",this.id)).append(Restrictions.ne("state",Short.valueOf("-1")));
    if (incomeBillReadRepository.getCount(incomeWp) > 0) {
      throw new BusinessException(this.name+"存未取消的收入单！反开账失败！");
    }
    StockLossReadRepository stockLossReadRepository = (StockLossReadRepository) SpringContextUtils.getBean("stockLossRepositoryImpl");
    Wrapper stockLossWp = Wrapper.build().append(Restrictions.eq("businessEntityId",this.id)).append(Restrictions.ne("status",Short.valueOf("-1")));
    if (stockLossReadRepository.getCount(stockLossWp) > 0) {
      throw new BusinessException(this.name+"存未取消的报损单！反开账失败！");
    }
    StockSpillReadRepository stockSpillReadRepository = (StockSpillReadRepository) SpringContextUtils.getBean("stockSpillRepositoryImpl");
    Wrapper stockSpillWp = Wrapper.build().append(Restrictions.eq("businessEntityId",this.id)).append(Restrictions.ne("status",Short.valueOf("-1")));
    if (stockSpillReadRepository.getCount(stockSpillWp) > 0) {
      throw new BusinessException(this.name+"存未取消的报溢单！反开账失败！");
    }
    StockOtherInBillReadRepository stockOtherInBillReadRepository = (StockOtherInBillReadRepository) SpringContextUtils.getBean("stockOtherInBillRepositoryImpl");
    Wrapper otherInWp = Wrapper.build().append(Restrictions.eq("businessEntityId",this.id)).append(Restrictions.ne("status",Short.valueOf("-1")));
    if (stockOtherInBillReadRepository.getCount(otherInWp) > 0) {
      throw new BusinessException(this.name+"存未取消的其他入库单！反开账失败！");
    }
    StockOtherOutBillReadRepository stockOtherOutBillReadRepository = (StockOtherOutBillReadRepository) SpringContextUtils.getBean("stockOtherOutBillRepositoryImpl");
    Wrapper otherOutWp = Wrapper.build().append(Restrictions.eq("businessEntityId",this.id)).append(Restrictions.ne("status",Short.valueOf("-1")));
    if (stockOtherOutBillReadRepository.getCount(otherOutWp) > 0) {
      throw new BusinessException(this.name+"存未取消的其他出库单！反开账失败！");
    }
    this.openAccountState = 0;
    this.openAccountTimeStamp = null;
  }

  /**
   * 数据销毁
   */
  public void destroy() {
    if (this.status.equals(Short.valueOf("1"))) {
      throw new BusinessException("供应商已启用,删除失败!");
    }
    //TODO 检查帐号
    //TODO 检查金融合作

  }
}
